﻿using System.Threading.Channels;

namespace ChannelDemo
{
    #region Channel Demo 01
    //internal class Program
    //{
    //    static Channel<Message> channel = Channel.CreateUnbounded<Message>();

    //    static Thread sender = new Thread(SendMeassageThread);
    //    static Thread receiver = new Thread(ReceiveMeassageThread);
    //    static void Main(string[] args)
    //    {
    //        sender.Start(1); ;
    //        receiver.Start(2);

    //        sender.Join();
    //        Thread.Sleep(1000); receiver.Interrupt();
    //        receiver.Join();
    //        Console.WriteLine("Hello, World!");

    //        Console.ReadKey();
    //    }

    //    static void SendMeassageThread(object? arg)
    //    {
    //        int id = (int)arg!;
    //        for (int i = 1; i < 20; i++)
    //        {
    //            if (channel.Writer.TryWrite(new Message(id, $"Message {i} from thread {id}")))
    //                Console.WriteLine($"Thread {id} sent {i}");

    //            Thread.Sleep(100);
    //        }
    //    }

    //    static void ReceiveMeassageThread(object? id)
    //    {
    //        try
    //        {
    //            while (true)
    //            {
    //                if (channel.Reader.TryRead(out Message message))
    //                {
    //                    Console.WriteLine($"Thread {id} received message {message.id}: {message.content}");
    //                    Thread.Sleep(1);
    //                }
    //            }
    //        }
    //        catch (Exception)
    //        {

    //            throw;
    //        }
    //    }
    //} 
    #endregion

    #region Channel Demo 02  Channel的异步版本
    internal class Program
    {
        static Channel<Message> channel = Channel.CreateUnbounded<Message>();

       
        static async Task Main(string[] args)
        {
            Task sender1 = SendMeassageAsync(channel.Writer, 1);
            Task sender2 = SendMeassageAsync(channel.Writer, 2);
            Task sender3 = SendMeassageAsync(channel.Writer, 3);
            await Task.WhenAll(sender1, sender2, sender3);
            Task receiver1 = ReceiveMeassageAsync(channel.Reader, 4);
            channel.Writer.Complete();
            await receiver1;
            Console.ReadKey();
        }

        static async Task SendMeassageAsync(ChannelWriter<Message> writer, int id)
        {
            for (int i = 1; i < 20; i++)
            {
                await writer.WriteAsync(new Message(id, i.ToString()));
                Console.WriteLine($"Thread {id} sent {i}");
                await Task.Delay(100);
            }
        }

        static async Task ReceiveMeassageAsync(ChannelReader<Message> reader, int id)
        {
            //try
            //{
            //    while (!reader.Completion.IsCompleted)
            //    {                    
            //        var message = await reader.ReadAsync();
            //        Console.WriteLine($"Thread {id} received message {message.content} from {message.id}");
            //    }
            //}
            //catch (ChannelClosedException)
            //{
            //    Console.WriteLine($"Thread {id} channel closed");
            //}


            //使用await foreach 即IAsyncEnumerable接口取代对于Completed状态的观察以及 ChannelClosedException异常的捕获
            await foreach (var message  in  reader.ReadAllAsync())
            {
                Console.WriteLine($"Thread {id} received message {message.content} from {message.id}");
            }
        }
    } 
    #endregion

    public record class Message(int id,string content);
}
